<template>
  <page-content :center="true">
    <lz-form
      :pass_delete="form.is_virtual"
      ref="form"
      :get-data="getData"
      :submit="onSubmit"
      :errors.sync="errors"
      :form.sync="form"
      :inDialog="true"
      disable-stay
      disable-redirect
      edit-mode
    > 
      <lz-form-item 
        >
        <div style="width: 100%;">
          <a-divider :dashed="true"/>
          <space class="my-1 header-actions">
            <router-link target='_blank' :to="`/system-models/${form.parent_id}`">
              <a-button>查看所有字段</a-button>
            </router-link>
            <doc-preview
              :label="`列表页字段总览`"
              :title="`列表页字段总览`"
              :content="listFields"
            />
            <doc-preview
              :label="`详情页字段总览`"
              :title="`详情页字段总览`"
              :content="detailFields"
            />
            <doc-preview
              :label="`搜索栏字段总览`"
              :title="`搜索栏字段总览`"
              :content="searchFields"
            />
            <doc-preview
              :label="`表单页字段总览`"
              :title="`表单页字段总览`"
              :content="formFields"
            />
          </space>
          <space class="my-1 header-actions">
            <doc-preview
              :label="`字段类型总览`"
              :title="`字段类型总览`"
              :content="fieldTypes"
            />
            <doc-preview
              :label="`验证规则总览`"
              :title="`验证规则总览`"
              :content="validationRules"
            />
            <doc-preview
              :label="`筛选规则总览`"
              :title="`筛选规则总览`"
              :content="filterRules"
            />
          </space>
          <a-divider :dashed="true"/>
        </div>
      </lz-form-item>

      <!-- 虚拟字段 -->
      <template v-if="form.is_virtual">
        <lz-form-item 
          label="虚拟字段标识" 
          prop="slug" 
          required
          :style="this.inLine50"
        >
          <a-input v-model="form.slug" type="input"/>
        </lz-form-item>
        <lz-form-item 
          label="虚拟字段名称" 
          prop="name" 
          required
          :style="this.inLine50"
        >
          <a-input v-model="form.name" type="input"/>
        </lz-form-item>
        <lz-form-item 
          label="默认值" 
          prop="value"
          :tip="`显示的默认值`"
        >
          <a-input v-model="form.value" type="input"/>
        </lz-form-item>
        <lz-form-item 
          label="列表页是否隐藏" 
          prop="list_hide"
          :style="this.inLine20"
        >
          <a-switch v-model="form.list_hide"/>
        </lz-form-item>
        <lz-form-item 
          label="详情页是否隐藏" 
          prop="detail_hide"
          :style="this.inLine20"
        >
          <a-switch v-model="form.detail_hide"/>
        </lz-form-item>
        <lz-form-item 
          label="列表页宽度" 
          prop="list_width"
          :style="this.inLine20"
        >
          <a-select v-model="form.list_width">
            <a-select-option key="50">50</a-select-option>
            <a-select-option key="100">100</a-select-option>
            <a-select-option key="150">150</a-select-option>
            <a-select-option key="200">200</a-select-option>
          </a-select>
        </lz-form-item>
        <lz-form-item 
          label="列表页固定" 
          prop="list_fixed"
          :style="this.inLine20"
        >
          <a-select v-model="form.list_fixed">
            <a-select-option :key="null">不固定</a-select-option>
            <a-select-option key="left">左侧</a-select-option>
            <a-select-option key="right">右侧</a-select-option>
          </a-select>
        </lz-form-item>
      </template>

      <!-- 真实字段 -->
      <template v-else>
        <lz-form-item 
          label="字段标识" 
          prop="slug" 
          :style="this.inLine20"
        >
          <p>{{ form.slug }}</p>
        </lz-form-item>
        <lz-form-item 
          label="字段名称" 
          prop="name" 
          :style="this.inLine20"
        >
          <p>{{ form.name }}</p>
        </lz-form-item>
        <lz-form-item 
          label="字段别名"
          prop="alias" 
          :tip="`用于表单中的标题，若字段别名为空，则显示字段名称。`"
          :style="this.inLine50"
        >
          <a-input v-model="form.alias" type="input"/>
        </lz-form-item>
        <lz-form-item 
          label="字段描述" 
          prop="desc"
          :tip="`用于表单中的提示`"
        >
          <a-input 
            v-model="form.desc" 
            type="textarea"
            rows="4"
          />
        </lz-form-item>
        <lz-form-item 
          label="列表页宽度" 
          prop="list_width"
          :style="this.inLine20"
        >
          <a-select v-model="form.list_width">
            <a-select-option key="50">50</a-select-option>
            <a-select-option key="100">100</a-select-option>
            <a-select-option key="150">150</a-select-option>
            <a-select-option key="200">200</a-select-option>
          </a-select>
        </lz-form-item>
        <lz-form-item 
          label="列表页固定" 
          prop="list_fixed"
          :style="this.inLine20"
        >
          <a-select v-model="form.list_fixed">
            <a-select-option :key="null">不固定</a-select-option>
            <a-select-option key="left">左侧</a-select-option>
            <a-select-option key="right">右侧</a-select-option>
          </a-select>
        </lz-form-item>
        <lz-form-item 
          label="字段类型" 
          prop="type" 
          :tip="`用于表单中的展示方式`"
          required
          :style="this.inLine50"
        >
          <a-select
            v-model="form.type"
            placeholder="选择类型"
            allow-clear
            show-search
            option-filter-prop="name"
          >
            <a-select-option
              v-for="i of types"
              :key="i.value"
              :name="i.label"
            >
              {{ i.label }}
            </a-select-option>
          </a-select>
        </lz-form-item>
        <lz-form-item 
          label="选项" 
          prop="options"
        >
          <type-options v-model="form.options" :type="form.type"/>
        </lz-form-item>
        <lz-form-item 
          label="默认值" 
          prop="value"
          :tip="`表单的默认值`"
        >
          <type-input
            v-model="form.value"
            :type="form.type"
            :options="form.options"
            :config_options="config_options"
          />
        </lz-form-item>
        <lz-form-item 
          label="表单验证规则" 
          :tip="`提交表单的验证规则`"
          prop="validation_rules" 
        >
          <a-table 
            :row-selection="rowSelection" 
            rowKey="key"
            :columns="columns" 
            :data-source="validation_rules"
            :expandIconAsCell="false" 
            :expandIconColumnIndex="1"
            :pagination="true"
            size="small"
            bordered
          >
            <div
              slot="filterDropdown"
              slot-scope="{ setSelectedKeys, selectedKeys, confirm, clearFilters, column }"
              style="padding: 4px"
            >
              <a-input
                v-ant-ref="c => (searchInput = c)"
                :placeholder="`${column.title}`"
                :value="selectedKeys[0]"
                style="width: 114px; margin-bottom: 4px; display: block;"
                @change="e => setSelectedKeys(e.target.value ? [e.target.value] : [])"
                @pressEnter="() => handleSearch(selectedKeys, confirm, column.dataIndex)"
              />
              <a-button
                type="primary"
                size="small"
                style="width: 55px; margin-right: 4px"
                @click="() => handleSearch(selectedKeys, confirm, column.dataIndex)"
              >
                搜索
              </a-button>
              <a-button size="small" style="width: 55px" @click="() => handleReset(clearFilters)">
                重置
              </a-button>
            </div>
            <a-icon
              slot="filterIcon"
              slot-scope="filtered"
              type="search"
              :style="{ color: filtered ? '#108ee9' : undefined }"
            />
            <template slot="customRender" slot-scope="text, record, index, column">
              <span v-if="searchText && searchedColumn === column.dataIndex">
                <template
                  v-for="(fragment, i) in text
                    .toString()
                    .split(new RegExp(`(?<=${searchText})|(?=${searchText})`, 'i'))"
                >
                  <mark
                    v-if="fragment.toLowerCase() === searchText.toLowerCase()"
                    :key="i"
                    class="highlight"
                    >{{ fragment }}</mark
                  >
                  <template v-else>{{ fragment }}</template>
                </template>
              </span>
              <template v-else>
                {{ text }}
              </template>
            </template>
            <template slot="param0_value" slot-scope="text,record">
              <template v-if="record.param0_key">
                <editable-cell 
                  :text="text" 
                  :placeholder="record.param0_key" 
                  @change="onCellChange(record.key, 'param0_value', $event)" 
                  v-model="validation_params[record.key][0]"
                />
              </template>
            </template>
            <template slot="param1_value" slot-scope="text,record">
              <template v-if="record.param1_key">
                <editable-cell 
                  :text="text" 
                  :placeholder="record.param1_key" 
                  @change="onCellChange(record.key, 'param1_value', $event)" 
                  v-model="validation_params[record.key][1]"
                />
              </template>
            </template>
          </a-table>
        </lz-form-item>
        <lz-form-item 
          label="列表筛选规则" 
          prop="filter_rules"
          :tip="`列表搜索的筛选规则`"
        >
          <a-auto-complete
            v-model="form.filter_rules"
            :data-source="filter_rules"
          />
        </lz-form-item>
        <lz-form-item 
          label="列表页是否隐藏" 
          prop="list_hide"
          :style="this.inLine20"
        >
          <a-switch v-model="form.list_hide"/>
        </lz-form-item>
        <lz-form-item 
          label="搜索栏是否隐藏" 
          prop="search_hide"
          :style="this.inLine20"
        >
          <a-switch v-model="form.search_hide"/>
        </lz-form-item>
        <lz-form-item 
          label="详情页是否隐藏" 
          prop="detail_hide"
          :style="this.inLine20"
        >
          <a-switch v-model="form.detail_hide"/>
        </lz-form-item>
        <lz-form-item 
          label="表单页是否隐藏" 
          prop="form_hide"
          :style="this.inLine20"
        >
          <a-switch v-model="form.form_hide"/>
        </lz-form-item>
        <lz-form-item 
          label="表单输入框是否禁用" 
          prop="form_disabled"
          :style="this.inLine20"
        >
          <a-switch v-model="form.form_disabled"/>
        </lz-form-item>
      </template>
      
    </lz-form>
    <div>
      <a-anchor
        :affix="true"
        :get-current-anchor="getCurrentAnchor"
        :target-offset="targetOffset"
      >
        <a-anchor-link 
          :title="`${parent.name}:${parent.slug}`"
        >
          <a-anchor-link 
            v-for="field of fields" 
            :href="`#/system-models/${form.parent_id}/edit?id=${field.id}`" 
            :title="`${field.name}:${field.slug}`"
          />
        </a-anchor-link>
      </a-anchor>
    </div>
  </page-content>
</template>

<script>
const columns = [
  {
    title: '验证规则',
    dataIndex: 'key',
    scopedSlots: { customRender: 'key' },
    scopedSlots: {
      filterDropdown: 'filterDropdown',
      filterIcon: 'filterIcon',
      customRender: 'customRender',
    },
    onFilter: (value, record) =>
      record.key
        .toString()
        .toLowerCase()
        .includes(value.toLowerCase()),
    onFilterDropdownVisibleChange: visible => {
      if (visible) {
        setTimeout(() => {
          this.searchInput.focus();
        }, 0);
      }
    },
  },
  {
    title: '描述',
    dataIndex: 'description',
    scopedSlots: { customRender: 'description' },
    scopedSlots: {
      filterDropdown: 'filterDropdown',
      filterIcon: 'filterIcon',
      customRender: 'customRender',
    },
    onFilter: (value, record) =>
      record.description
        .toString()
        .toLowerCase()
        .includes(value.toLowerCase()),
    onFilterDropdownVisibleChange: visible => {
      if (visible) {
        setTimeout(() => {
          this.searchInput.focus();
        }, 0);
      }
    },
  },
  {
    title: '参数一',
    dataIndex: 'param0_value',
    scopedSlots: { customRender: 'param0_value' },
  },
  {
    title: '参数二',
    dataIndex: 'param1_value',
    scopedSlots: { customRender: 'param1_value' },
  }
];

import LzForm from '@c/LzForm'
import { mapConstants } from '@/libs/constants'
import {
  createSystemModel,
  editSystemModel,
  storeSystemModel,
  updateSystemModel,
  getSystemModelsField,
} from '@/api/system-models'
import {
  getParseOptions
} from '@/api/configs'
import {
  inArray,
} from '@/libs/utils'
import _forIn from 'lodash/forIn'
import TypeOptions from '../configs/components/TypeOptions'
import TypeInput from '../configs/components/TypeInput'
import PageContent from '@c/PageContent'
import LzFormItem from '@c/LzForm/LzFormItem'
import EditableCell from '@c/EditableCell'
import DocPreview from '@c/DocPreview'
import Space from '@c/Space'

export default {
  name: 'Form',
  components: {
    LzFormItem,
    PageContent,
    TypeInput,
    TypeOptions,
    LzForm,
    EditableCell,
    DocPreview,
    Space
  },
  data() {
    return {
      form: {
        id: 0,
        parent_id: 0,
        name: '',
        alias: '',
        slug: '',
        type: '',
        desc: '',
        options: {},
        value: '',
        validation_rules: [],
        filter_rules: '',
        is_virtual: false,
        list_hide: false,
        search_hide: false,
        detail_hide: false,
        form_hide: false,
        form_disabled: false,
        list_width: 150,
        list_fixed: null,
      },
      parent: {},
      fields: [],
      errors: {},
      types: [],
      filter_rules: [],
      validation_rules: [],
      validation_params: {"accepted":[],"active_url":[],"after":[],"after_or_equal":[],"alpha":[],"alpha_dash":[],"alpha_num":[],"array":[],"before":[],"before_or_equal":[],"between":[],"boolean":[],"confirmed":[],"date":[],"date_equals":[],"date_format":[],"different":[],"digits":[],"digits_between":[],"dimensions":[],"distinct":[],"email":[],"ends_with":[],"exists":[],"file":[],"filled":[],"gt":[],"gte":[],"image":[],"in":[],"in_array":[],"integer":[],"ip":[],"ipv4":[],"ipv6":[],"json":[],"lt":[],"lte":[],"max":[],"mimes":[],"mimetypes":[],"min":[],"not_in":[],"not_regex":[],"numeric":[],"password":[],"present":[],"regex":[],"required":[],"required_if":[],"required_unless":[],"required_with":[],"required_with_all":[],"required_without":[],"required_without_all":[],"same":[],"size":[],"starts_with":[],"string":[],"timezone":[],"unique":[],"uploaded":[],"url":[],"uuid":[]},
      cates: [],
      config_options: {},
      columns,
      selectedRowKeys: [],
      inLine20: {
        display: 'inline-block',
        width: '20%'
      },
      inLine50: {
        display: 'inline-block',
        width: '50%'
      },
      targetOffset: undefined,
      searchText: '',
      searchInput: null,
      searchedColumn: '',
      listFields: [],
      searchFields: [],
      formFields: [],
      detailFields: [],
      rules: [],
      validationRules: [],
      filterRules: [],
      fieldTypes: [],
    }
  },
  created() {
    this.getSystemModelsField(this.$route.params.id)
  },
  mounted() {
    this.targetOffset = window.innerHeight / 2;
  },
  computed: {
    ...mapConstants(['CONFIG_TYPES']),
    rowSelection() {
      return {
        onChange: (selectedRowKeys) => {
          this.selectedRowKeys = selectedRowKeys
        },
        getCheckboxProps: record => {
          return {
            props: {
              defaultChecked: this.selectedRowKeys.includes(record.key)
            }
          };
        }
      };
    },
  },
  methods: {
    handleSearch(selectedKeys, confirm, dataIndex) {
      confirm();
      this.searchText = selectedKeys[0];
      this.searchedColumn = dataIndex;
    },
    handleReset(clearFilters) {
      clearFilters();
      this.searchText = '';
    },
    getCurrentAnchor() {
      return '#/system-models/'+this.$route.params.id+'/edit?id='+this.$route.query.id;
    },
    onCellChange(key, dataIndex, value) {
      const validation_rules = [...this.validation_rules];
      const target = validation_rules.find(item => item.key === key);
      if (target) {
        target[dataIndex] = value;
        this.validation_rules = validation_rules;
      }
    },
    async getData($form) {
      let data
      if ($form.realEditMode) {
        ({ data } = await editSystemModel($form.resourceId, {id:this.$route.query.id}))
      } else {
        ({ data } = await createSystemModel())
      }
      const options = await getParseOptions({
        type:data.data.type,
        options:data.data.options,
        scene:'form',
      })
      this.config_options = options.data.options
      this.parent = data.data.parent
      this.fields = data.data.fields
      this.cates = data.categories
      const types = []
      _forIn(data.types_map, (value, key) => {
        types.push({
          value: key,
          label: value,
        })
      })
      this.types = types
      // 表单中类型，默认选择第一个
      this.form.type = types[0].value

      // 筛选规则
      const filter_rules = []
      _forIn(data.filter_rules_map, (value) => {
        filter_rules.push(JSON.stringify(value))
      })
      this.filter_rules = filter_rules

      // 验证规则
      this.selectedRowKeys = [];
      if ( data.data.validation_rules ) {
        const validationRules = data.data.validation_rules.split('|')
        validationRules.forEach((validationRule) => {
          const validationRuleArr = validationRule.split(':')
          // 回显选择框
          this.selectedRowKeys.push(validationRuleArr[0])
        })
      }
      
      data.validation_rules_map.forEach((i) => {
        i.description = i.description.replace(':attribute', data.data.slug)
        // 回显参数值
        if (i.param0_value) {
          this.validation_params[i.key][0] = i.param0_value
        }
        if (i.param1_value) {
          this.validation_params[i.key][1] = i.param1_value
        }
      })
      this.validation_rules = data.validation_rules_map

      this.validationRules = '<pre>'+JSON.stringify(data.validationRules[data.data.parent_id], null, 4)+'</pre>'
      this.filterRules = '<pre>'+JSON.stringify(data.filterRules[data.data.parent_id], null, 4)+'</pre>'
      this.fieldTypes = '<pre>'+JSON.stringify(data.fieldTypes[data.data.parent_id], null, 4).replace(/\\/g,"\\\\")+'</pre>'
      return data.data
    },
    async onSubmit($form) {
      const selectedRowKeys = this.selectedRowKeys.toString().split(',')
      const validationParamKeys = []
      const validationRules = [];
      _forIn(this.validation_params, (value, key) => {
        if (inArray(key,selectedRowKeys) && value.length>0) {
          validationRules.push(key+':'+value.join(','))
          validationParamKeys.push(key)
        }
      })
      _forIn(selectedRowKeys, (value) => {
        if (!inArray(value,validationParamKeys)) {
          validationRules.push(value)
        }
      })
      this.form.validation_rules = validationRules.join('|')
      if ($form.realEditMode) {
        this.form.id = this.$route.query.id
        await updateSystemModel($form.resourceId, this.form)
      } else {
        await storeSystemModel(this.form)
      }
    },
    async getSystemModelsField() {
      const { data: { 
        filter_rules_map, 
        listFields,
        searchFields, 
        formFields,
        detailFields, 
      } } = await getSystemModelsField(this.$route.params.id)
      this.listFields = '<pre>'+JSON.stringify(listFields, null, 4)+'</pre>'
      this.searchFields = '<pre>'+JSON.stringify(searchFields, null, 4)+'</pre>'
      this.formFields = '<pre>'+JSON.stringify(formFields, null, 4)+'</pre>'
      this.detailFields = '<pre>'+JSON.stringify(detailFields, null, 4)+'</pre>'

      // 筛选规则
      const rules = []
      _forIn(filter_rules_map, (value) => {
        rules.push(JSON.stringify(value))
      })
      this.rules = rules

      this.$scrollResolve()
    },
  },
}
</script>
<style>
.highlight {
  background-color: rgb(255, 192, 105);
  padding: 0px;
}
.ant-anchor-wrapper {
  margin-left: 30px;
}
.header-actions {
  width: 100%;
  overflow-x: auto;
}
</style>
